home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume26 / cputt-2.3 / part01 next >
Encoding:
Text File  |  1993-04-05  |  27.0 KB  |  850 lines

  1. Newsgroups: comp.sources.unix
  2. From: vesper@kong.gsfc.nasa.gov (Greg Vesper - 520.9)
  3. Subject: v26i103: cputt - cpu status monitor for sunos, V2.3, Part01/01
  4. Sender: unix-sources-moderator@vix.com
  5. Approved: paul@vix.com
  6.  
  7. Submitted-By: vesper@kong.gsfc.nasa.gov (Greg Vesper - 520.9)
  8. Posting-Number: Volume 26, Issue 103
  9. Archive-Name: cputt-2.3/part01
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 1 (of 1)."
  18. # Contents:  MANIFEST Makefile README UNSHAR.HDR cputt.c cputt.h
  19. #   getcmd.c globals.c hash.c init.c routines.c
  20. # Wrapped by vixie@gw.home.vix.com on Tue Apr  6 03:42:49 1993
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  24. else
  25. echo shar: Extracting \"'MANIFEST'\" \(455 characters\)
  26. sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  27. X   File Name        Archive #    Description
  28. X-----------------------------------------------------------
  29. X MANIFEST                   1    This shipping list
  30. X Makefile                   1    
  31. X README                     1    
  32. X UNSHAR.HDR                 1    
  33. X cputt.c                    1    
  34. X cputt.h                    1    
  35. X getcmd.c                   1    
  36. X globals.c                  1    
  37. X hash.c                     1    
  38. X init.c                     1    
  39. X routines.c                 1    
  40. END_OF_FILE
  41. if test 455 -ne `wc -c <'MANIFEST'`; then
  42.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  43. fi
  44. # end of 'MANIFEST'
  45. fi
  46. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  47.   echo shar: Will not clobber existing file \"'Makefile'\"
  48. else
  49. echo shar: Extracting \"'Makefile'\" \(484 characters\)
  50. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  51. PROG    = cputt
  52. OBJS    =    globals.o init.o getcmd.o hash.o routines.o cputt.o
  53. CC      = cc
  54. CFLAGS  =    -Isys
  55. LIBS    = -lkvm
  56. DIRINSTALL = /usr/local/bin
  57. X
  58. all:      $(PROG)
  59. X
  60. X.c.o:
  61. X        $(CC) $(CFLAGS) -c -O $<
  62. X
  63. X$(OBJS):  cputt.h
  64. X
  65. X$(PROG):  $(OBJS)
  66. X        $(CC) -o $@ $(OBJS) $(LIBS)
  67. X
  68. install:  $(PROG)
  69. X        strip $(PROG)
  70. X        cp $(PROG) $(DIRINSTALL)/$(PROG)
  71. X        /etc/chown root $(DIRINSTALL)/$(PROG)
  72. X        chgrp kmem $(DIRINSTALL)/$(PROG)
  73. X        chmod 2755 $(DIRINSTALL)/$(PROG)
  74. X
  75. clean:
  76. X        rm -f $(OBJS) $(PROG)
  77. END_OF_FILE
  78. if test 484 -ne `wc -c <'Makefile'`; then
  79.     echo shar: \"'Makefile'\" unpacked with wrong size!
  80. fi
  81. # end of 'Makefile'
  82. fi
  83. if test -f 'README' -a "${1}" != "-c" ; then 
  84.   echo shar: Will not clobber existing file \"'README'\"
  85. else
  86. echo shar: Extracting \"'README'\" \(3874 characters\)
  87. sed "s/^X//" >'README' <<'END_OF_FILE'
  88. X          Cputt - CPU Top Ten monitor for SUNOS 4.1.1
  89. X          ===========================================
  90. X                        Version 2.3
  91. X
  92. DISCLAIMER:
  93. X
  94. X     This software has no warranty whatsoever, explicit or implicit.
  95. X     The author and his employer shall not be held liable for any
  96. X     damage, direct or indirect, resulting from the use of this
  97. X     software.  That being said, feel free to use it, its a handy
  98. X     little utility.
  99. X
  100. PURPOSE:
  101. X
  102. X     Cputt is a cpu monitoring utility for SunOS 4.1.1.  It gives you a
  103. X     continuous update of the top ten cpu-using processes on your
  104. X     system.
  105. X
  106. CHANGES:
  107. X
  108. X     Version 2.3 contains a bug fix which allows Cputt to run on Sun 3's.
  109. X     It now assigns default values if invoked without parameters.  The
  110. X     source has been neatened up as well.
  111. X
  112. IMPLEMENTATION:
  113. X
  114. X     Cputt takes two snapshots of the kernel process table, sleeping
  115. X     for a user supplied number of seconds in between the two
  116. X     snapshots.  It calculates cpu usage for each process over that
  117. X     interval and prints out the results.  Execution continues for a
  118. X     user supplied number of iterations.
  119. X
  120. USAGE:
  121. X
  122. X     Cputt should be invoked with two arguments as follows:
  123. X
  124. X          cputt <length of interval> <number of iterations>
  125. X
  126. X     Cputt prints a sorted list of cpu intensive processes as follows:
  127. X
  128. X          PID  USER  CPU  MEM  COMMANDS  <active processes> <ptable size>
  129. X
  130. INSTALLATION:
  131. X
  132. X     Cputt should compile on any system running SunOS 4.1.1.  Check
  133. X     the #define values in cputt.h before compiling.  The only one
  134. X     you need to change is MAXUSERS which should be two times the
  135. X     number of /etc/passwd entries on your machine.  Just type
  136. X     'make' to compile, 'make install' to install.  You must be root
  137. X     to install Cputt.  The default destination is /usr/local/bin.
  138. X
  139. SUGGESTION:
  140. X
  141. X     Cputt becomes more and more processor intensive as the length of the
  142. X     interval between process table lookups decreases.  Thus a first
  143. X     arguement of less than 4 is probably not real useful.  I usually
  144. X     invoke it with one of the following:
  145. X
  146. X     cputt 5  10   - for short term monitoring of cpu usage (default)
  147. X     cputt 10 100  - for long term monitoring of cpu usage
  148. X     cputt 20 1000 - for real long term monitoring of cpu usage
  149. X
  150. ACKNOWLEDGEMENTS:
  151. X
  152. X     The idea for Cputt came from Larry Schuler, a friend and co-worker.
  153. X     The implementation for Cputt was largely dependent on J. Robert Ward's
  154. X     'sps' utility.  I used Robert's source code to learn how to make the 
  155. X     appropriate system calls for interrogating the kernel process table.
  156. X     The rest of the algorithm and implementation are my own.
  157. X
  158. IMPROVEMENTS:
  159. X
  160. X     I've used all the shortcuts I know to make Cputt as trim as possible.
  161. X     Floating point arithmetic is kept to a bare minimum.  Internal data
  162. X     structures are allocated dynamically based on the changing status of
  163. X     the process table.  Command arguements for each process are kept in
  164. X     core instead of being re-evaluated at each iteration.  The sort table
  165. X     contains only active processes and no extraneous information.  The
  166. X     kernel reads account for the bulk of Cputt's processing overhead and
  167. X     I'm unaware of anyway to alleviate this cost.  If anyone has any well
  168. X     considered suggestions about how I can improve the implemenation and
  169. X     performance of Cputt, I would like to hear them.
  170. X
  171. COPYRIGHT:
  172. X
  173. X     Feel free to distribute Cputt to any interested parties.  Please
  174. X     provide a copy of this README with any distribution.
  175. X
  176. X:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  177. X              Greg Vesper Code 520.9
  178. X           Goddard Space Flight Center
  179. X            vesper@kong.gsfc.nasa.gov
  180. X               Greenbelt, Maryland
  181. X
  182. X"As He died to make men holy, let us live to make men free.
  183. X:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  184. END_OF_FILE
  185. if test 3874 -ne `wc -c <'README'`; then
  186.     echo shar: \"'README'\" unpacked with wrong size!
  187. fi
  188. # end of 'README'
  189. fi
  190. if test -f 'UNSHAR.HDR' -a "${1}" != "-c" ; then 
  191.   echo shar: Will not clobber existing file \"'UNSHAR.HDR'\"
  192. else
  193. echo shar: Extracting \"'UNSHAR.HDR'\" \(1160 characters\)
  194. sed "s/^X//" >'UNSHAR.HDR' <<'END_OF_FILE'
  195. Return-Path: vesper@kong.gsfc.nasa.gov
  196. Received: by cognition.pa.dec.com; id AA22597; Mon, 27 Apr 92 08:07:55 -0700
  197. Received: by inet-gw-2.pa.dec.com; id AA22182; Mon, 27 Apr 92 08:07:50 -0700
  198. Received: from relay2.UU.NET by rodan.UU.NET with SMTP (5.61/UUNET-mail-drop) id AA01224; Mon, 27 Apr 92 11:07:46 -0400
  199. Received: from lego.gsfc.nasa.gov by relay2.UU.NET with SMTP (5.61/UUNET-internet-primary) id AA11514; Mon, 27 Apr 92 11:07:48 -0400
  200. Received: from kong.gsfc.nasa.gov by lego.gsfc.nasa.gov (5.61/1.35)id AA20539; Mon, 27 Apr 92 11:07:28 -0400
  201. Received: by kong.gsfc.nasa.gov (4.1/SMI-4.1)id AA07425; Mon, 27 Apr 92 11:07:28 EDT
  202. Newsgroups: comp.sources.unix
  203. Path: vesper
  204. XFrom: vesper@kong.gsfc.nasa.gov (Greg Vesper - 520.9)
  205. Subject: Cputt - Version 2.3
  206. Message-Id: <1992Apr27.150723.7382@kong.gsfc.nasa.gov>
  207. Sender: vesper@kong.gsfc.nasa.gov (Greg Vesper - 520.9)
  208. Organization: Goddard Space Flight Center
  209. Date: Mon, 27 Apr 92 15:07:23 GMT
  210. Lines: 688
  211. Apparently-To: comp-sources-unix@uunet.uu.net
  212. X
  213. This is the latest version of 'cputt' - a cpu monitoring utility for SunOS
  214. X4.1.1.  It contains an important bug fix which allows it run on Sun 3's.
  215. X
  216. END_OF_FILE
  217. if test 1160 -ne `wc -c <'UNSHAR.HDR'`; then
  218.     echo shar: \"'UNSHAR.HDR'\" unpacked with wrong size!
  219. fi
  220. # end of 'UNSHAR.HDR'
  221. fi
  222. if test -f 'cputt.c' -a "${1}" != "-c" ; then 
  223.   echo shar: Will not clobber existing file \"'cputt.c'\"
  224. else
  225. echo shar: Extracting \"'cputt.c'\" \(7269 characters\)
  226. sed "s/^X//" >'cputt.c' <<'END_OF_FILE'
  227. X#include     <sys/types.h>
  228. X#include     <sys/stat.h>
  229. X#include     <sys/timeb.h>
  230. X#include     <sys/user.h>
  231. X#include     <sys/resource.h>
  232. X#include     <kvm.h>
  233. X#include     <fcntl.h>
  234. X
  235. X#include     "cputt.h"
  236. X
  237. X/*
  238. X   MAIN - Computes CPU utilization for all processes from two snapshots
  239. X   of the kernel process table taken over a user supplied interval
  240. X   (arg1).  Sorts and prints the top ten CPU using processes for that
  241. X   interval.  Execution continues for a user supplied number of
  242. X   iterations (arg2).
  243. X
  244. X   The kernel process table snapshots are stored in two arrays,
  245. X   'oldproc' and 'newproc'.  Resource utilization information is stored
  246. X   in two arrays, 'oldusage' and 'newusage'.  The command strings for
  247. X   each process are stored in a 2D array, 'cmds'.  CPU utilization for
  248. X   each interval is stored in the 'sdata' array along with pointers to
  249. X   the appropriate 'proc' and 'cmds' entries.
  250. X*/
  251. X
  252. main (argc, argv)
  253. X
  254. int argc; char *argv[];
  255. X
  256. X{
  257. X     struct proc              *oldproc,*newproc,*tproc;
  258. X     struct rusage            *oldusage,*newusage,*tusage;
  259. X     struct sortdata          *sdata;
  260. X     struct hashtab           *hp;
  261. X
  262. X     register long             time1,utime1,time2,utime2;
  263. X     register long             s_delta,p_delta;
  264. X     register int              i,last,sindex;
  265. X
  266. X     struct timeb              ot,nt;
  267. X     struct hashtab           *hashuid();
  268. X     int                       reps,interval,iterations,cmp();
  269. X     double                    percentmem();
  270. X     char                     **cmds;
  271. X
  272. X     /* check arguements */
  273. X
  274. X     switch(argc) 
  275. X     {
  276. X         case 3:
  277. X            interval = atoi(argv[1]);
  278. X            iterations = atoi(argv[2]);
  279. X            break;
  280. X         case 1:
  281. X            interval=5;
  282. X            iterations=10;
  283. X            break;
  284. X         default:
  285. X            printf("Usage: cputt <interval> <iterations>\n");
  286. X            exit(1);
  287. X     }
  288. X
  289. X     setpriority(PRIO_PROCESS,0,-20);
  290. X
  291. X     /* open kernel memory  */
  292. X
  293. X     if(!(Flkvm = kvm_open(NULL, NULL, NULL, O_RDONLY, "cputt")))
  294. X        exit(1);
  295. X
  296. X     /* get critical system parameters, build uid hash table */
  297. X
  298. X     printf("Initializing..\n");
  299. X     init();
  300. X     initusers();
  301. X
  302. X     /* truncate unused portion of the process table */
  303. X
  304. X     Info.i_sproc = Info.i_nproc * sizeof(struct proc);
  305. X     if (GROWTH_BUF)
  306. X     {
  307. X         oldproc = (struct proc *) getcore(Info.i_nproc*sizeof(struct proc));
  308. X         readstatus(oldproc);
  309. X         for (i=0; i<Info.i_nproc; i++)
  310. X              if (oldproc[i].p_stat && getupage(&oldproc[i]))
  311. X              {
  312. X                  last=i;
  313. X              }
  314. X         free(oldproc);
  315. X         if (last+GROWTH_BUF < Info.i_nproc)
  316. X         {
  317. X             Info.i_nproc = last+GROWTH_BUF;
  318. X             Info.i_sproc = Info.i_nproc * sizeof(struct proc);
  319. X         }
  320. X     }
  321. X
  322. X     /* allocate core for internal data structures */
  323. X     cmds = (char **) getcore(Info.i_nproc*sizeof(char *));
  324. X     for (i=0;i<Info.i_nproc;i++)
  325. X          cmds[i] = (char *) getcore(COMMAND_SIZE);
  326. X
  327. X     sdata     = (struct sortdata *)
  328. X                  getcore(MAXACTIVE*sizeof(struct sortdata));
  329. X     oldusage  = (struct rusage *)
  330. X                  getcore(Info.i_nproc*sizeof(struct rusage));
  331. X     newusage  = (struct rusage *)
  332. X                  getcore(Info.i_nproc*sizeof(struct rusage));
  333. X     oldproc   = (struct proc *) getcore(Info.i_nproc*sizeof(struct proc));
  334. X     newproc   = (struct proc *) getcore(Info.i_nproc*sizeof(struct proc));
  335. X
  336. X     /* get initial time, process table, upage, and command strings */
  337. X
  338. X     ftime(&ot);
  339. X     readstatus(oldproc);
  340. X     for (i=0;i<Info.i_nproc;i++) 
  341. X          if (oldproc[i].p_stat && getupage(&oldproc[i]))
  342. X             {
  343. X              oldusage[i] = User.u_us.u_ru;
  344. X              getcmd(&oldproc[i],cmds[i]);
  345. X             }
  346. X
  347. X     /* compare process tables every argv[1] seconds for argv[2] iterations */
  348. X
  349. X     for (reps = 0; reps < iterations; reps++)
  350. X     {    
  351. X          sleep(interval);         /* sleep for agrv[1] seconds */
  352. X          ftime(&nt);                  /* get new time          */
  353. X          readstatus(newproc);         /* get new process table */
  354. X
  355. X          /* find matching pids, compute cpu usage, store results in sdata */
  356. X
  357. X          for (sindex=i=0; i<Info.i_nproc; i++)
  358. X               if (newproc[i].p_stat && getupage(&newproc[i]))
  359. X               {
  360. X                   last=i; /* record latest proc table location */
  361. X                   newusage[i] = User.u_us.u_ru;
  362. X                   if (oldproc[i].p_pid==newproc[i].p_pid)
  363. X                   {
  364. X                       time1 =   oldusage[i].ru_utime.tv_sec +
  365. X                                 oldusage[i].ru_stime.tv_sec;
  366. X                       utime1 =  oldusage[i].ru_utime.tv_usec +
  367. X                                 oldusage[i].ru_stime.tv_usec;
  368. X                       time2 =   newusage[i].ru_utime.tv_sec +
  369. X                                 newusage[i].ru_stime.tv_sec;
  370. X                       utime2 =  newusage[i].ru_utime.tv_usec +
  371. X                                 newusage[i].ru_stime.tv_usec;
  372. X                       p_delta = (time2*1000000+utime2) -
  373. X                                 (time1*1000000+utime1);
  374. X                       if (p_delta)
  375. X                       {
  376. X                           s_delta = (nt.time*1000+nt.millitm) -
  377. X                                     (ot.time*1000+ot.millitm);
  378. X                           sdata[sindex].pctcpu = (p_delta*10)/s_delta;
  379. X                           sdata[sindex].proc   = &oldproc[i];
  380. X                           sdata[sindex].pr_cmd = i;
  381. X
  382. X                           if (sindex < MAXACTIVE - 1)
  383. X                               sindex++;
  384. X                           else
  385. X                               printf("\ncputt: MAXACTIVE limit exceeded.\n");
  386. X                       }
  387. X                   }
  388. X                   else
  389. X                   {
  390. X                       getcmd(&newproc[i],cmds[i]);
  391. X                   }
  392. X               } 
  393. X
  394. X          /* check process table variance at each iteration */
  395. X
  396. X          if (GROWTH_BUF &&
  397. X             (i-last < GROWTH_BUF-MAX_GROW || i-last > GROWTH_BUF+MAX_SHRINK))
  398. X          {
  399. X              printf("\nProcess table variance greater than %d, restarting..\n",
  400. X                      MAX_GROW + MAX_SHRINK);
  401. X              execvp(argv[0],argv);
  402. X          }
  403. X
  404. X          /* sort and print results */
  405. X
  406. X          qsort(sdata,sindex,sizeof(struct sortdata),cmp); 
  407. X          printf("\n  PID USER        CPU    MEM  COMMANDS - %d %d\n"
  408. X                 ,sindex,last);
  409. X          for (i=--sindex; sindex > -1 && sindex > i-MAXOUT; --sindex)
  410. X          {
  411. X               printf("%5d ",sdata[sindex].proc->p_pid);
  412. X               if (hp = hashuid(sdata[sindex].proc->p_suid))
  413. X                   printf("%-8.8s ",hp->h_uname);
  414. X               else
  415. X                   printf("user%-4.4d ",sdata[sindex].proc->p_uid);
  416. X               printf("%6.2f ",(float)sdata[sindex].pctcpu/100);
  417. X               printf("%6.2f ",percentmem(sdata[sindex].proc));
  418. X               printf(" %s\n",cmds[sdata[sindex].pr_cmd]);
  419. X          }
  420. X       
  421. X          /* swap old and new pointers */
  422. X
  423. X          tusage   = oldusage;   tproc   = oldproc;
  424. X          oldusage = newusage;   oldproc = newproc;
  425. X          newusage = tusage;     newproc = tproc;
  426. X          ot = nt;
  427. X
  428. X     }    /* for all iterations.. */
  429. X
  430. X}    /* main */
  431. END_OF_FILE
  432. if test 7269 -ne `wc -c <'cputt.c'`; then
  433.     echo shar: \"'cputt.c'\" unpacked with wrong size!
  434. fi
  435. # end of 'cputt.c'
  436. fi
  437. if test -f 'cputt.h' -a "${1}" != "-c" ; then 
  438.   echo shar: Will not clobber existing file \"'cputt.h'\"
  439. else
  440. echo shar: Extracting \"'cputt.h'\" \(2203 characters\)
  441. sed "s/^X//" >'cputt.h' <<'END_OF_FILE'
  442. X#define MAXUSERS       300 /* set this to (length of /etc/passwd * 2) */
  443. X#define MAXACTIVE       50 /* max cpu-positive processes per interval */
  444. X#define MAXOUT          10 /* output is limitted to this many processes */
  445. X#define COMMAND_SIZE    51 /* set this to (width of your window - 29) */
  446. X#define UNAMELEN         8 /* max length for username */
  447. X
  448. X/*
  449. X   cputt attempts to truncate unused slots at the end of the process
  450. X   table.  This usually reduces its runtime size considerably.  If the
  451. X   process table grows or shrinks by a significant amount, cputt will
  452. X   restart itself and resize its internal data structures accordingly.
  453. X*/
  454. X
  455. X#define GROWTH_BUF      40 /* growth buffer, use 0 to disable truncation */
  456. X#define MAX_GROW        20 /* restart after proc table grows this much */
  457. X#define MAX_SHRINK      10 /* restart after proc table shrinks this much */
  458. X
  459. X/* Symbol table entry and value */
  460. X
  461. struct symbol
  462. X{
  463. X     char          *s_kname;            /* kernel symbol name */
  464. X     caddr_t       *s_info;             /* kernel symbol value */
  465. X};
  466. X
  467. X/* Single hash table entry for mapping uid's to usernames */
  468. X
  469. struct hashtab
  470. X{
  471. X     short          h_uid;              /* uid of user entry */
  472. X     char           h_uname[UNAMELEN];  /* corresponding name */
  473. X};
  474. X
  475. X/* Critical system info */
  476. X
  477. struct info
  478. X{
  479. X     struct proc   *i_proc0;            /* address of process table */
  480. X     int            i_nproc;            /* length of process table */
  481. X     int            i_sproc;            /* size of process table */
  482. X     int            i_ecmx;             /* max physical memory address*/
  483. X     struct hashtab i_hnames[MAXUSERS]; /* hash table for usernames */
  484. X};
  485. X
  486. X/* For reading process upages from kernel memory */
  487. X
  488. union userstate
  489. X{
  490. X     struct user     u_us;
  491. X     char            u_pg[UPAGES][NBPG];
  492. X};
  493. X
  494. X/* Summary info for processes with positive cpu utilization */
  495. X
  496. struct sortdata
  497. X{
  498. X     struct proc    *proc;              /* proc structure */
  499. X     long            pctcpu;            /* cpu usage */
  500. X     int             pr_cmd;            /* command string index */
  501. X};
  502. X
  503. extern kvm_t          *Flkvm;
  504. extern union userstate User;
  505. extern struct symbol   Symbollist[];
  506. extern struct info     Info;
  507. END_OF_FILE
  508. if test 2203 -ne `wc -c <'cputt.h'`; then
  509.     echo shar: \"'cputt.h'\" unpacked with wrong size!
  510. fi
  511. # end of 'cputt.h'
  512. fi
  513. if test -f 'getcmd.c' -a "${1}" != "-c" ; then 
  514.   echo shar: Will not clobber existing file \"'getcmd.c'\"
  515. else
  516. echo shar: Extracting \"'getcmd.c'\" \(1031 characters\)
  517. sed "s/^X//" >'getcmd.c' <<'END_OF_FILE'
  518. X#include     <sys/user.h>
  519. X#include     <kvm.h>
  520. X#include     "cputt.h"
  521. X
  522. X/* GETCMD - gets the command string for process p and copies it to argbuf */
  523. void
  524. getcmd(p,argbuf)
  525. struct proc *p;
  526. register char *argbuf;
  527. X{
  528. X     register char           *cp,**ap;
  529. X     char                    **argv;
  530. X     register int            sp=-1;
  531. X
  532. X     if (!p->p_pid)
  533. X        { strcpy(&argbuf[0],"Swapper"); return; }
  534. X     if (p->p_pid == 2)
  535. X        { strcpy(&argbuf[0],"Pager"); return; }
  536. X
  537. X     if (kvm_getcmd(Flkvm,p,&User.u_us,&argv,(char ***)NULL)<0||argv==NULL)
  538. X     {
  539. X         argbuf[0] = '(';
  540. X         strncpy(&argbuf[1],User.u_us.u_comm,sizeof(User.u_us.u_comm));
  541. X         argbuf[sizeof(User.u_us.u_comm)+1] = '\0';
  542. X         strcat(argbuf,")");
  543. X     }
  544. X     else
  545. X     {
  546. X         ap = argv;
  547. X         while (*ap && sp < COMMAND_SIZE-1)
  548. X         {
  549. X             for (cp = *ap++; *cp && sp < COMMAND_SIZE-2;)
  550. X                  argbuf[++sp] = *cp++;
  551. X             argbuf[++sp] = ' ';
  552. X         }
  553. X         argbuf[sp] = '\0';
  554. X         free(argv);
  555. X     }
  556. X}
  557. END_OF_FILE
  558. if test 1031 -ne `wc -c <'getcmd.c'`; then
  559.     echo shar: \"'getcmd.c'\" unpacked with wrong size!
  560. fi
  561. # end of 'getcmd.c'
  562. fi
  563. if test -f 'globals.c' -a "${1}" != "-c" ; then 
  564.   echo shar: Will not clobber existing file \"'globals.c'\"
  565. else
  566. echo shar: Extracting \"'globals.c'\" \(627 characters\)
  567. sed "s/^X//" >'globals.c' <<'END_OF_FILE'
  568. X#include     <sys/user.h>
  569. X#include     <kvm.h>
  570. X#include     "cputt.h"
  571. X
  572. struct info                     Info;  /* System Addresses and Info */
  573. X
  574. kvm_t                          *Flkvm; /* Descriptor for Kernel Memory */
  575. X
  576. union  userstate                User;  /* Structure to Hold Upages */
  577. X
  578. struct symbol   Symbollist[] =         /* Symbols to Lookup */
  579. X{
  580. X     { "_proc",  (caddr_t*)&Info.i_proc0 }, /* Process table base */
  581. X     { "_nproc", (caddr_t*)&Info.i_nproc }, /* Max number of processes */
  582. X     { "_maxmem",(caddr_t*)&Info.i_ecmx  }, /* Max real memory */
  583. X     { (char*)0, (caddr_t*)0             }  /* NULL entry */
  584. X};
  585. END_OF_FILE
  586. if test 627 -ne `wc -c <'globals.c'`; then
  587.     echo shar: \"'globals.c'\" unpacked with wrong size!
  588. fi
  589. # end of 'globals.c'
  590. fi
  591. if test -f 'hash.c' -a "${1}" != "-c" ; then 
  592.   echo shar: Will not clobber existing file \"'hash.c'\"
  593. else
  594. echo shar: Extracting \"'hash.c'\" \(1001 characters\)
  595. sed "s/^X//" >'hash.c' <<'END_OF_FILE'
  596. X#include     <sys/user.h>
  597. X#include     <kvm.h>
  598. X#include     <pwd.h>
  599. X#include     "cputt.h"
  600. X
  601. X#define       HASHFN1(a) (((unsigned)(a)*91 + 17) % MAXUSERS)
  602. X
  603. X/*
  604. X   HASHUID - Returns a pointer to a slot in the hash table that corresponds
  605. X   to the hash table entry for `uid'. It returns a null pointer if there is
  606. X   no such slot.
  607. X*/
  608. X
  609. struct hashtab *
  610. hashuid(uid)
  611. int      uid;
  612. X{
  613. X     struct hashtab *hp;
  614. X
  615. X     hp = &Info.i_hnames[HASHFN1(uid)];
  616. X     if (hp->h_uid == uid)
  617. X         return(hp);
  618. X     return(0);
  619. X}
  620. X
  621. X/*
  622. X   INITUSERS - builds the uid hash table.
  623. X*/
  624. X
  625. void
  626. initusers ()
  627. X{
  628. X     struct passwd  *pw;
  629. X     struct hashtab *hp;
  630. X     struct passwd  *getpwent();
  631. X
  632. X     while (pw = getpwent())
  633. X     {
  634. X          /* Try to find a free slot in the hash table and fill it. */
  635. X
  636. X          hp = &Info.i_hnames[HASHFN1(pw->pw_uid)];
  637. X          if (!hp->h_uname[0])
  638. X          {
  639. X               hp->h_uid = pw->pw_uid;
  640. X               strncpy(hp->h_uname,pw->pw_name,UNAMELEN);
  641. X          }
  642. X     }
  643. X     endpwent();
  644. X}
  645. END_OF_FILE
  646. if test 1001 -ne `wc -c <'hash.c'`; then
  647.     echo shar: \"'hash.c'\" unpacked with wrong size!
  648. fi
  649. # end of 'hash.c'
  650. fi
  651. if test -f 'init.c' -a "${1}" != "-c" ; then 
  652.   echo shar: Will not clobber existing file \"'init.c'\"
  653. else
  654. echo shar: Extracting \"'init.c'\" \(1547 characters\)
  655. sed "s/^X//" >'init.c' <<'END_OF_FILE'
  656. X#include     <stdio.h>
  657. X#include     <nlist.h>
  658. X#include     <sys/file.h>
  659. X#include     <sys/user.h>
  660. X#include     <kvm.h>
  661. X
  662. X#include     "cputt.h"
  663. X
  664. X/*
  665. X   INIT - Gets symbol table values for symbols in Symbollist.
  666. X*/
  667. X
  668. void
  669. init()
  670. X{
  671. X     register struct nlist   *np;
  672. X     register struct symbol  *s;
  673. X     register struct nlist   *np0;
  674. X     char                    *getcore();
  675. X
  676. X     /* find length of the list of desired symbols */
  677. X     for (s = Symbollist; s->s_kname; s++);
  678. X
  679. X     /* allocate core for nlist array */
  680. X     np0 = (struct nlist*)getcore((s-Symbollist+1)*sizeof(struct nlist));
  681. X
  682. X     /* initialize nlist array */
  683. X     for (s = Symbollist,np = np0; s->s_kname; s++,np++)
  684. X     {
  685. X          np->n_name = s->s_kname;
  686. X          np[1].n_name = (char*)0;
  687. X          np->n_value = 0;
  688. X     }
  689. X
  690. X     /* read symbols from symbol table into nlist array */
  691. X     if (kvm_nlist(Flkvm,np0) == -1)
  692. X     {
  693. X          fprintf(stderr,"sps - Can't read symbol file \n");
  694. X          sysperror();
  695. X     }
  696. X
  697. X     /* derive system info from nlist and store in Symbollist */
  698. X     for (s = Symbollist,np = np0; s->s_kname; s++,np++)
  699. X     {                                       
  700. X          if (!np->n_value)             
  701. X          {
  702. X              fprintf( stderr, "sps - Can't find symbol %s in %s", np->n_name);
  703. X              *s->s_info = (caddr_t)0;
  704. X              continue;
  705. X          }
  706. X
  707. X          /* Using the obtained address, read the value into Symbollist */
  708. X          (void)getkmem((long)np->n_value, (char*)s->s_info, sizeof(caddr_t));
  709. X     }
  710. X     free((char*)np0);
  711. X}
  712. END_OF_FILE
  713. if test 1547 -ne `wc -c <'init.c'`; then
  714.     echo shar: \"'init.c'\" unpacked with wrong size!
  715. fi
  716. # end of 'init.c'
  717. fi
  718. if test -f 'routines.c' -a "${1}" != "-c" ; then 
  719.   echo shar: Will not clobber existing file \"'routines.c'\"
  720. else
  721. echo shar: Extracting \"'routines.c'\" \(2263 characters\)
  722. sed "s/^X//" >'routines.c' <<'END_OF_FILE'
  723. X#include     <stdio.h>
  724. X#include     <sys/user.h>
  725. X#include     <kvm.h>
  726. X#include     "cputt.h"
  727. X
  728. X/*
  729. X   GETUPAGE - Reads the upage for the specified process as well as sufficient
  730. X   page tables entries for reading the command arguments. The pte's are read
  731. X   into the argument `p'. The upage is read into the external variable
  732. X   `User'. Returns 1 if the upage was successfully read.
  733. X*/
  734. X
  735. getupage(p)
  736. register struct proc *p;
  737. X{
  738. X     struct user *upage;
  739. X
  740. X     if (upage = kvm_getu(Flkvm,p))
  741. X     {
  742. X          bcopy((char *)upage,User.u_pg[0],sizeof(struct user));
  743. X          return(1);
  744. X     }
  745. X/*
  746. X     fprintf(stderr,"cputt - Can't read upage of process %d s= %o f= %o\n",
  747. X             p->p_pid,p->p_stat,p->p_flag) ;
  748. X*/
  749. X     return(0);
  750. X}
  751. X
  752. X/* READSTATUS - Reads process table from kernel memory */
  753. X
  754. void
  755. readstatus(ptable)
  756. struct proc *ptable;
  757. X{
  758. X     if (getkmem((long)Info.i_proc0,(char*)ptable,Info.i_sproc)!=Info.i_sproc)
  759. X     {
  760. X          fprintf(stderr,"cputt - Can't read system process table\n" );
  761. X          exit();
  762. X     }
  763. X}
  764. X
  765. X/* PERCENTMEM - Returns the percentage of real memory used by this process */
  766. X
  767. double
  768. percentmem(p)
  769. struct proc *p;
  770. X{
  771. X     double fracmem;
  772. X
  773. X     if (!(p->p_flag & SLOAD))
  774. X          return (0.0);
  775. X     fracmem = ((double)p->p_rssize + UPAGES);
  776. X     return(100.0 * fracmem / (double)Info.i_ecmx);
  777. X}
  778. X
  779. X/* GETKMEM - read kernel memory */
  780. X
  781. getkmem(addr,buf,bufsize)
  782. long    addr;
  783. char    *buf;
  784. int     bufsize;
  785. X{
  786. X     return(kvm_read(Flkvm,(long)addr,buf,bufsize));
  787. X}
  788. X
  789. X/* SYSPERROR - Reports a system defined error msg and then exits gracefully */
  790. X
  791. void
  792. sysperror ()
  793. X{
  794. X     extern int  errno;
  795. X     extern int  sys_nerr;
  796. X     extern char *sys_errlist[];
  797. X
  798. X     if (0 < errno && errno < sys_nerr)
  799. X         fprintf(stderr," : %s",sys_errlist[errno]);
  800. X     (void)fputc('\n',stderr);
  801. X     exit(1);
  802. X}
  803. X
  804. X/* GETCORE - Allocate and return a pointer to the asked for amount of core */
  805. X
  806. char *
  807. getcore(size)
  808. register int     size ;
  809. X{
  810. X     register char  *chp;
  811. X     char           *malloc();
  812. X
  813. X     if (chp = malloc((unsigned)size))
  814. X         return(chp);
  815. X     fprintf(stderr,"cputt - Out of core");
  816. X     sysperror();
  817. X}
  818. X
  819. X/* CMP - used by qsort() to perform comparisons */
  820. X
  821. cmp(p1,p2)
  822. register struct sortdata *p1,*p2;
  823. X{
  824. X     return(p1->pctcpu - p2->pctcpu);
  825. X}   
  826. END_OF_FILE
  827. if test 2263 -ne `wc -c <'routines.c'`; then
  828.     echo shar: \"'routines.c'\" unpacked with wrong size!
  829. fi
  830. # end of 'routines.c'
  831. fi
  832. echo shar: End of archive 1 \(of 1\).
  833. cp /dev/null ark1isdone
  834. MISSING=""
  835. for I in 1 ; do
  836.     if test ! -f ark${I}isdone ; then
  837.     MISSING="${MISSING} ${I}"
  838.     fi
  839. done
  840. if test "${MISSING}" = "" ; then
  841.     echo You have the archive.
  842.     rm -f ark[1-9]isdone
  843. else
  844.     echo You still need to unpack the following archives:
  845.     echo "        " ${MISSING}
  846. fi
  847. ##  End of shell archive.
  848. exit 0
  849.